package com.atmilan.quartz.sync.pull.buyer.service.impl;

import java.time.Instant;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.atmilan.quartz.model.dto.buyer.BuyerBrandResult;
import com.atmilan.quartz.model.dto.buyer.BuyerCateResult;
import com.atmilan.quartz.model.dto.buyer.BuyerOrderDTO;
import com.atmilan.quartz.model.dto.buyer.BuyerProductResDTO;
import com.atmilan.quartz.provider.IBuyerProvider;
import com.atmilan.quartz.sync.pull.buyer.service.IBuyerService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import cn.hutool.core.map.MapUtil;
import cn.hutool.crypto.digest.DigestUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * @author hupeng
 */
@Slf4j
@Service
public class BuyerServiceImpl implements IBuyerService {

    @Value("${buyer.appkey}")
    private String appKey;
    @Value("${buyer.appsecret}")
    private String appSecret;

    public static final String BUYER_OP = "goods";
    public static final String BUYER_ACTION = "list";


    public static final String BUYER_CAT_OP = "filter";
    public static final String BUYER_CAT_ACTION = "cat";


    public static final String BUYER_BRAND_OP = "filter";
    public static final String BUYER_BRAND_ACTION = "brand";


    public static final String BUYER_ORDER_OP = "order";
    public static final String BUYER_ORDER_ACTION = "update_order";


    private final IBuyerProvider provider;

    @Autowired
    public BuyerServiceImpl(IBuyerProvider provider) {
        this.provider = provider;
    }
    
    public static void main(String[] args) {
        Map<String, String> signMap = MapUtil.newHashMap(4);
        signMap.put("timeStamp", "1614828361");
        signMap.put("randomStr", "12345");
        signMap.put("appkey", "milan");
        signMap.put("appsecret", "5f3199c139bafa807a548884fa6eeefb");

        List<String> valueList = signMap.entrySet()
                .stream()
                .sorted(Map.Entry.comparingByValue())
                .map(Map.Entry::getValue)
                .collect(Collectors.toList());

        String signStr = StringUtils.join(valueList, null);
        signStr = DigestUtil.sha1Hex(signStr);
        signStr = DigestUtil.md5Hex(signStr);
        signStr = DigestUtil.md5Hex(signStr);

        System.out.println(signStr.toUpperCase());
    }

    @Override
    public BuyerProductResDTO getProduct(int page, int pageSize) {
        String timestamp = String.valueOf(Instant.now().getEpochSecond());
        String random = String.valueOf(ThreadLocalRandom.current().nextInt(1000, 9999));
        String signature = this.getSignature(timestamp, random);
        return this.provider.getProduct(BUYER_OP, BUYER_ACTION, random, timestamp, appKey, appSecret, signature, page, pageSize, 1);
    }

    @Override
    public String getProductStr(int page,int pageSize) {
        String timestamp = String.valueOf(Instant.now().getEpochSecond());
        String random = String.valueOf(ThreadLocalRandom.current().nextInt(1000, 9999));
        String signature = this.getSignature(timestamp, random);
        return this.provider.getProductStr(BUYER_OP, BUYER_ACTION, random, timestamp, appKey, appSecret, signature, page, pageSize);
    }

    @Override
    public BuyerCateResult getCate() {
        String timestamp = String.valueOf(Instant.now().getEpochSecond());
        String random = String.valueOf(ThreadLocalRandom.current().nextInt(1000, 9999));
        String signature = this.getSignature(timestamp, random);
        return this.provider.getCate(BUYER_CAT_OP, BUYER_CAT_ACTION, random, timestamp, appKey, appSecret, signature);
    }

    @Override
    public BuyerBrandResult getBrand() {
        String timestamp = String.valueOf(Instant.now().getEpochSecond());
        String random = String.valueOf(ThreadLocalRandom.current().nextInt(1000, 9999));
        String signature = this.getSignature(timestamp, random);
        return this.provider.getBrand(BUYER_BRAND_OP, BUYER_BRAND_ACTION, random, timestamp, appKey, appSecret, signature);
    }

    @Override
    public String getBrandString() {
        String timestamp = String.valueOf(Instant.now().getEpochSecond());
        String random = String.valueOf(ThreadLocalRandom.current().nextInt(1000, 9999));
        String signature = this.getSignature(timestamp, random);
        return this.provider.getBrandString(BUYER_BRAND_OP, BUYER_BRAND_ACTION, random, timestamp, appKey, appSecret, signature);
    }

    @Override
    public String pushOrder(BuyerOrderDTO order) {
        String timestamp = String.valueOf(Instant.now().getEpochSecond());
        String random = String.valueOf(ThreadLocalRandom.current().nextInt(1000, 9999));
        String signature = this.getSignature(timestamp, random);
        try {
            String data = new ObjectMapper().writeValueAsString(order);
            return this.provider.pushOrder(BUYER_ORDER_OP, BUYER_ORDER_ACTION, random, timestamp, appKey, appSecret, signature,data);
        } catch (JsonProcessingException e) {
            log.error("push order failed ! order:{}",order,e);
        }
        return null;
    }

    private String getSignature(String timestamp, String random) {
        Map<String, String> signMap = MapUtil.newHashMap(4);
        signMap.put("timeStamp", timestamp);
        signMap.put("randomStr", random);
        signMap.put("appkey", this.appKey);
        signMap.put("appsecret", this.appSecret);

        List<String> valueList = signMap.entrySet()
                .stream()
                .sorted(Map.Entry.comparingByValue())
                .map(Map.Entry::getValue)
                .collect(Collectors.toList());

        String signStr = StringUtils.join(valueList, null);
        signStr = DigestUtil.sha1Hex(signStr);
        signStr = DigestUtil.md5Hex(signStr);
        signStr = DigestUtil.md5Hex(signStr);

        return signStr.toUpperCase();
    }
}
